import { EditorView } from "@codemirror/view";
import { Extension } from "@codemirror/state";
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
import { tags as t } from "@lezer/highlight";

export const config = {
    name: "obsidian",
    dark: false,
    background: "var(--background-primary)",
    foreground: "var(--text-normal)",
    selection: "var(--text-selection)",
    cursor: "var(--text-normal)",
    dropdownBackground: "var(--background-primary)",
    dropdownBorder: "var(--background-modifier-border)",
    activeLine: "var(--background-primary)",
    matchingBracket: "var(--background-modifier-accent)",
    keyword: "#d73a49",
    storage: "#d73a49",
    variable: "var(--text-normal)",
    parameter: "var(--text-accent-hover)",
    function: "var(--text-accent-hover)",
    string: "var(--text-accent)",
    constant: "var(--text-accent-hover)",
    type: "var(--text-accent-hover)",
    class: "#6f42c1",
    number: "var(--text-accent-hover)",
    comment: "var(--text-faint)",
    heading: "var(--text-accent-hover)",
    invalid: "var(--text-error)",
    regexp: "var(--text-accent)",
};

export const obsidianTheme = EditorView.theme(
    {
        "&": {
            color: config.foreground,
            backgroundColor: config.background,
        },

        ".cm-content": { caretColor: config.cursor },

        "&.cm-focused .cm-cursor": { borderLeftColor: config.cursor },
        "&.cm-focused .cm-selectionBackground, .cm-selectionBackground, & ::selection":
            { backgroundColor: config.selection },

        ".cm-panels": {
            backgroundColor: config.dropdownBackground,
            color: config.foreground,
        },
        ".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
        ".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },

        ".cm-searchMatch": {
            backgroundColor: config.dropdownBackground,
            outline: `1px solid ${config.dropdownBorder}`,
        },
        ".cm-searchMatch.cm-searchMatch-selected": {
            backgroundColor: config.selection,
        },

        ".cm-activeLine": { backgroundColor: config.activeLine },
        ".cm-activeLineGutter": { backgroundColor: config.background },
        ".cm-selectionMatch": { backgroundColor: config.selection },

        ".cm-matchingBracket, .cm-nonmatchingBracket": {
            backgroundColor: config.matchingBracket,
            outline: "none",
        },
        ".cm-gutters": {
            backgroundColor: config.background,
            color: config.comment,
            borderRight: "1px solid var(--background-modifier-border)",
        },
        ".cm-lineNumbers, .cm-gutterElement": { color: "inherit" },

        ".cm-foldPlaceholder": {
            backgroundColor: "transparent",
            border: "none",
            color: config.foreground,
        },

        ".cm-tooltip": {
            border: `1px solid ${config.dropdownBorder}`,
            backgroundColor: config.dropdownBackground,
            color: config.foreground,
        },
        ".cm-tooltip.cm-tooltip-autocomplete": {
            "& > ul > li[aria-selected]": {
                background: config.selection,
                color: config.foreground,
            },
        },
    },
    { dark: config.dark },
);

export const obsidianHighlightStyle = HighlightStyle.define([
    { tag: t.keyword, color: config.keyword },
    {
        tag: [t.name, t.deleted, t.character, t.macroName],
        color: config.variable,
    },
    { tag: [t.propertyName], color: config.function },
    {
        tag: [
            t.processingInstruction,
            t.string,
            t.inserted,
            t.special(t.string),
        ],
        color: config.string,
    },
    { tag: [t.function(t.variableName), t.labelName], color: config.function },
    {
        tag: [t.color, t.constant(t.name), t.standard(t.name)],
        color: config.constant,
    },
    { tag: [t.definition(t.name), t.separator], color: config.variable },
    { tag: [t.className], color: config.class },
    {
        tag: [
            t.number,
            t.changed,
            t.annotation,
            t.modifier,
            t.self,
            t.namespace,
        ],
        color: config.number,
    },
    { tag: [t.typeName], color: config.type, fontStyle: config.type },
    { tag: [t.operator, t.operatorKeyword], color: config.keyword },
    { tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp },
    { tag: [t.meta, t.comment], color: config.comment },
    { tag: t.strong, fontWeight: "bold" },
    { tag: t.emphasis, fontStyle: "italic" },
    { tag: t.link, textDecoration: "underline" },
    { tag: t.heading, fontWeight: "bold", color: config.heading },
    {
        tag: [t.atom, t.bool, t.special(t.variableName)],
        color: config.variable,
    },
    { tag: t.invalid, color: config.invalid },
    { tag: t.strikethrough, textDecoration: "line-through" },
]);

export const obsidian: Extension = [
    obsidianTheme,
    syntaxHighlighting(obsidianHighlightStyle),
];
